Release 10.1A: OpenEdge Development:
Progress 4GL Handbook


Super procedure example

To show some of the principles of super procedures in action, you can create one that manipulates windows in a simple way. The super procedure needs to have a single entry point, an internal procedure called alignWindow, to position all windows to the same column.

To create an example super procedure:

  1. From the AppBuilder, select New Structured Procedure.
  2. Make sure the Procedures toggle box is checked so that this nonvisual program template is in the list.
  3. Add a new procedure called alignWindow:
  4. /*--------------------------------------------------------------------- 
      Purpose:   Aligns all windows to the same column position.   
              
    ---------------------------------------------------------------------*/ 
      TARGET-PROCEDURE:CURRENT-WINDOW:COL = 20.0. 
      RETURN. 
    END PROCEDURE. 
    

    The TARGET-PROCEDURE handle is the handle of the window procedure that this is a super procedure for. The code simply sets its current window’s column position to 20. Note the use of chained attribute references. You can chain together as many object attributes as you need in a single expression, as long as all the attributes (except the last) evaluate to handles. Also, the COL attribute is of type DECIMAL, so don’t forget the decimal on the value 20.0.

    Structured procedures don’t have any visualization, so there’s no real design window for them in the AppBuilder. Instead, you get a window with a tree view with all the code sections.

  5. Expand the tree view and double-click on any section to bring it up in the Section Editor:
  6. Now you need a standard procedure that knows how to start a super procedure. It needs to determine whether it’s already running, run it if it’s not there, and then make it a super procedure of the requesting procedure.

  7. Define a new external procedure called h-StartSuper.p with this code:
  8. /* h-StartSuper.p -- starts a super procedure if not already running, 
      and returns its handle. */ 
      DEFINE INPUT  PARAMETER cProcName AS CHARACTER  NO-UNDO. 
      DEFINE VARIABLE hProc AS HANDLE     NO-UNDO. 
      /* Try to locate an instance of the procedure already running. */ 
      hProc = SESSION:FIRST-PROCEDURE. 
      DO WHILE VALID-HANDLE(hProc): 
          IF hProc:FILE-NAME = cProcName THEN 
             LEAVE.    /* found it. */ 
          hProc = hProc:NEXT-SIBLING. 
      END. 
      /* If it wasn't found, then run it. */ 
      IF NOT VALID-HANDLE(hProc) THEN 
          RUN VALUE(cProcName) PERSISTENT SET hProc. 
      /* In either case, add it as a super procedure of the caller. */ 
      SOURCE-PROCEDURE:ADD-SUPER-PROCEDURE(hProc, SEARCH-TARGET). 
    

    This code looks for a running instance of the procedure name passed in, using the SESSION procedure list. If it’s not there, it runs it. Then it adds it as a super procedure of the SOURCE-PROCEDURE, which is the procedure that ran h-StartSuper.p.

  9. Add statements to the main block of both h-CustOrderWin6.w and h-OrderWin.w to get h-StartSuper.p to start h-WinSuper.p and then to run alignWindow:
  10. MAIN-BLOCK: 
    DO ON ERROR  UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK 
      ON END-KEY UNDO MAIN-BLOCK, LEAVE MAIN-BLOCK: 
      RUN h-StartSuper.p (INPUT "h-WinSuper.p").  /* add this super procedure 
    */ 
      RUN alignWindow. 
      RUN enable_UI. 
      ASSIGN cState = Customer.State 
             iMatches = NUM-RESULTS("CustQuery"). 
      DISPLAY cState iMatches WITH FRAME CustQuery. 
      APPLY "VALUE-CHANGED" TO OrderBrowse. 
    END. 
    

To review what’s happening when you run h-CustOrderWin6.w again, look at the diagram in Figure 14–7.

Figure 14–7: Running the sample procedure with a super procedure

The dotted lines represent transient relationships that are only present during startup. Both h-CustOrderWin6.w and h-OrderWin.w run h-StartSuper.p to get their super procedure. When each runs it in turn, SOURCE-PROCEDURE points back to the procedure that ran it. h-StartSuper.p establishes h-WinSuper.p as the super procedure for each one in turn, and then goes away because it was not run persistent itself. It was only needed to set up the relationships.

Once the persistent procedures are all set up, each one runs alignWindow. There’s no alignWindow procedure in either of the .w’s, so Progress searches the super procedure stack and locates it in h-WinSuper.p and runs that code. Now alignWindow can refer to TARGET-PROCEDURE to access the window handle inside each of the .w’s.

To add another small layer of complexity:

  1. Add an implementation of alignWindow in h-CustOrderWin6.w:
  2. /*--------------------------------------------------------------------- 
      Purpose:     Local version of alignWindow for h-CustOrderWin 
                   to set ROW as well as column.    
    ---------------------------------------------------------------------*/ 
      RUN SUPER. 
      ASSIGN THIS-PROCEDURE:CURRENT-WINDOW:ROW = 10.0. 
    END PROCEDURE. 
    

    This code uses a RUN SUPER to invoke the standard behavior in h-WinSuper.p, and then adds some more code of its own, in this case to set the ROW attribute of the window.

    So the net effect of these two versions of alignWindow is to set both the COL and the ROW.

  3. Do the same thing in h-OrderWin.w. Define a version of alignWindow that sets ROW to something different from the local code in h-CustOrderWin6.w:
  4. /*--------------------------------------------------------------------- 
      Purpose:    Local version of alignWindow for OrderWin sets Row to 20.0. 
      Parameters: <none> 
      Notes:        
    ---------------------------------------------------------------------*/ 
      RUN SUPER. 
      THIS-PROCEDURE:CURRENT-WINDOW:ROW = 20.0. 
    END PROCEDURE. 
    

    Now all Order windows come up initially in the same place, on top of one another. You can drag them around to see all of them. The diagram in Figure 14–8 represents this second situation.

Figure 14–8: Variation on running the sample procedures with a super procedure

When Progress executes the RUN alignWindow statement, it finds the internal procedure locally and executes it. The local version first invokes the standard behavior in the super procedure and then extends it with its own custom code.

Super procedures might seem like a complicated mechanism, but consider that they are intended to allow you to provide standard behavior for many procedure objects. This means that you can carefully craft the super procedure code for a type of behavior, and then every other procedure that uses that super procedure inherits the behavior automatically and transparently. This is the power of super procedures.


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095